#include "GateSessionBase.h"
#include "IPacketParser.h"
#include "LogEx.h"
#include "StackTrace.h"
#include "Hall.h"
#include "Utils.h"
#include "msg_msgid.h"
#include "msg_common.h"
#include "msg_gate.h"
using namespace SGLib;

CGateSessionBase::CGateSessionBase(s32 id) : 
    CSessionBase( id ),
	m_curConn( 0 ),
	m_maxConn( 0 ),
	m_ip( "" ),
	m_port( 0 )
{
}

CGateSessionBase::~CGateSessionBase()
{
}

void CGateSessionBase::GetGateState(s32 &curConn, s32 &maxConn, std::string &ip, s32 &port)
{
	curConn = m_curConn;
	maxConn = m_maxConn;
	ip = m_ip;
	port = m_port;
}

void CGateSessionBase::SendMsgToGate(u32 msgid, const IMessage &msg)
{
	SendMsg( msgid, msg );
}

void CGateSessionBase::SendMsgToClients(s32 count, u64 *clients, u32 msgid, const IMessage &msg)
{
	if( count == 0 || !clients )
	{
        LOG_ERROR( "[%s][%s][%d] param error", __FILE__, __FUNCTION__, __LINE__ );
		return;
	}

	IPacketParser *parser = _GetPacketParser();
	SELF_ASSERT( parser, return; );

	// pack client msg
    CHECK_SERIALIZE_MSG(msgid, msg, parser, return;);

	gateproto::ServerGateMsg2Client req;
	for( s32 i=0; i<count; ++i )
	{
		req.clientid.push_back( clients[i] );
	}
	req.msg.append( (char*)msgbuffer, msglen );
	SendMsgToGate( msgid::SG_MSG_2_CLIENT, req );
#if DEBUG
    LOG_DEBUG( "[%s][%s][%d] clientid0[%llu] count[%d] msgid[%u] msglen[%d]", 
        __FILE__, __FUNCTION__, __LINE__, clients[0], count, msgid, msglen );
#endif
}

void CGateSessionBase::SendMsgToClient(u64 clientid, u32 msgid, const IMessage &msg)
{
	u64 clientids[] = { clientid, };
	SendMsgToClients( 1, clientids, msgid, msg );
}

const std::string& CGateSessionBase::GetIp()
{
	return m_ip;
}

s32 CGateSessionBase::GetPort()
{
	return m_port;
}

void CGateSessionBase::_OnMessage(u32 msgid, const byte *msg, s32 len)
{
	switch( msgid )
	{
	case msgid::GS_REPORT_CLIENT_CLOSE:
		_OnClientClose( msg, len );
		break;
	case msgid::GS_REPORT_STATUS:
		_OnGateReportStatus( msg, len );
		break;
	case msgid::GS_FORWARD_MSG:
		_OnForwardClientMsg( msg, len );
		break;
	default:
        LOG_ERROR( "[%s][%s][%d] msg[%u] len[%d]", __FILE__, __FUNCTION__, __LINE__, 
			msgid, len );
		break;
	};
}

CIoSocketEx* CGateSessionBase::Clone(s32 id)
{
    return new CGateSessionBase( id );
}

void CGateSessionBase::_OnClientClose(const byte *pkg, s32 len)
{
	gateproto::GateServerReportClientClose msg;
	if( msg.ParseFromArray((const char*)pkg, len) == len )
	{
        LOG_INFO( "[%s][%s][%d] client[%llu:%llu]", __FILE__, __FUNCTION__, __LINE__, GetServerId(), msg.clientid );
		CHall::Instance().OnMsgUserClose( GetServerId(), msg.clientid );
        //_OnClientClose( GetServerId(), msg.clientid );
	}
	else
	{
        LOG_INFO( "[%s][%s][%d] Parse faild. len[%d]", __FILE__, __FUNCTION__, __LINE__, len );
	}
}

void CGateSessionBase::_OnForwardClientMsg(const byte *pkg, s32 len)
{
	gateproto::GateForwardMsg msg;
	if( msg.ParseFromArray((const char*)pkg, len) == len )
	{
		u64 clientid = msg.clientid;
        u32 remoteip = msg.remoteip;

		IPacketParser *parser = _GetPacketParser();
		SELF_ASSERT( parser, return; );
		s32 headlen = parser->GetHeadLen();
		const byte *clientmsg = (const byte*)msg.msg.c_str();
		s32 msglen = (s32)msg.msg.length();
		u32 msgid = parser->GetMsgId( clientmsg );
		clientmsg += headlen;
		msglen -= headlen;

#if DEBUG
		LOG_DEBUG( "CGateSessionBase::_OnForwardClientMsg recv client[%llu:%llu] msg[%u:%d] ip[%s]", 
			GetServerId(), clientid, msgid, msglen, ConvertIp(remoteip).c_str() );
#endif
		if( GetServerId() == 0 )
		{
			LOG_ERROR( "CGateSessionBase::_OnForwardClientMsg gate[%llu] client[%llu] msg[%u:%d] not ready", 
				GetServerId(), clientid, msgid, msglen );
			return;
		}
		_OnClientMessage( GetServerId(), clientid, msgid, clientmsg, msglen, remoteip );
	}
	else
	{
		LOG_ERROR( "CGateSessionBase::_OnForwardClientMsg gate[%llu]", GetServerId() );
	}
}

void CGateSessionBase::_OnGateReportStatus(const byte *pkg, s32 len)
{
	gateproto::GateServerReportStatus msg;
	if( msg.ParseFromArray((const char*)pkg, len) == len )
	{
		LOG_INFO( "CGateSessionBase::GateServerReportStatusReq gate[%llu(%llu)] onlineinfo[%d/%d] gateinfo[%s:%d]",
			msg.gateid, GetServerId(), msg.cur_conn, msg.max_conn, msg.ip.c_str(), msg.port );
		
		m_curConn = msg.cur_conn;
		m_maxConn = msg.max_conn;
		m_ip = msg.ip;
		m_port = msg.port;
	}
	else
	{
		LOG_ERROR( "CGateSessionBase::_OnGateReportStatus ParseFromArray faild. msglen[%d]", len );
	}
}

void CGateSessionBase::_OnClientMessage(u64 gateid, u64 clientid, u32 msgid, const byte *msg, s32 len, u32 remoteip)
{
	switch( msgid )
	{
	case commonproto::CS_GAME_AUTHEN_REQ:
		CHall::Instance().OnMsgUserAuthenReq( gateid, clientid, msg, len );
		break;
	case commonproto::CS_ENTER_ROOM_REQ:
		CHall::Instance().OnMsgUserEnterRoomReq( gateid, clientid, msg, len );
		break;
	case commonproto::CS_LEAVE_ROOM_REQ:
		CHall::Instance().OnMsgUserLeaveRoomReq( gateid, clientid, msg, len );
		break;
	case commonproto::CS_SITDOWN_REQ:
		CHall::Instance().OnMsgUserSitDownReq( gateid, clientid, msg, len );
		break;
	case commonproto::CS_STANDUP_REQ:
		CHall::Instance().OnMsgUserStandUpReq( gateid, clientid, msg, len );
		break;
	case commonproto::CS_READY_REQ:
		CHall::Instance().OnMsgUserReady( gateid, clientid, msg, len );
		break;
	case commonproto::CS_CANCEL_READY_REQ:
		CHall::Instance().OnMsgUserCancelReady( gateid, clientid, msg, len );
		break;
    case commonproto::CS_TRUSTEESHIP_REQ:
		CHall::Instance().OnMsgUserTrusteeShip( gateid, clientid, msg, len );
        break;
    case commonproto::CS_CANCEL_TRUSTEESHIP_REQ:
		CHall::Instance().OnMsgUserCancelTrusteeShip( gateid, clientid, msg, len );
        break;
    case commonproto::CS_ROOM_CHAT_REQ:
		CHall::Instance().OnMsgUserRoomChat( gateid, clientid, msg, len );
        break;
    case commonproto::CS_CREATE_ROOM_REQ:
		CHall::Instance().OnMsgUserCreateRoom( gateid, clientid, msg, len );
        break;
    case commonproto::CS_MATCH_PLAYER_REQ:
		CHall::Instance().OnMsgMatchPlayer( gateid, clientid, msg, len );
        break;
    case commonproto::CS_SET_ROOM_ANTE_REQ:
		CHall::Instance().OnMsgSetRoomAnte( gateid, clientid, msg, len );
        break;
    case commonproto::CS_GET_ROOM_LIST_REQ:
		CHall::Instance().OnMsgGetRoomList( gateid, clientid, msg, len );
        break;
    case commonproto::CS_GET_ACTIVITY_AWARD_REQ:
		CHall::Instance().OnMsgGetActivityAward( gateid, clientid, msg, len );
        break;
    case commonproto::CS_FRIEND_ROOM_DISMISS_REQ:
		CHall::Instance().OnMsgFriendRoomDismiss( gateid, clientid, msg, len );
        break;
    case commonproto::CS_FRIEND_ROOM_LEAVE:
		CHall::Instance().OnMsgFriendRoomLeave( gateid, clientid, msg, len );
        break;
    case commonproto::CS_FRIEND_ROOM_AGREE_DISMISS:
		CHall::Instance().OnMsgFriendRoomAgreeDismiss( gateid, clientid, msg, len );
        break;
    case commonproto::CS_FRIEND_ROOM_START_GAME:
		CHall::Instance().OnMsgFriendRoomStartGame( gateid, clientid, msg, len );
        break;
    case commonproto::CS_SELF_LOCATION_INFO:
		CHall::Instance().OnMsgSelfLocationInfo( gateid, clientid, remoteip, msg, len );
        break;
    case commonproto::CS_KICKOUT_ROOM_REQ:
		CHall::Instance().OnMsgKickOutRoom( gateid, clientid, msg, len );
        break;
    case commonproto::CS_USE_INTERACT_ITEM_REQ:
        CHall::Instance().OnMsgUseInteractItem(gateid, clientid, msg, len);
        break;
    case commonproto::CS_USER_CUIPAI_REQ:
        CHall::Instance().OnMsgUserCuiPai(gateid, clientid, msg, len);
        break;
    case commonproto::CS_GET_USER_INFO_REQ:
        CHall::Instance().OnMsgGetUserInfo(gateid, clientid, msg, len);
        break;
	default:
		_OnOtherMessage( gateid, clientid, msgid, msg, len );
		break;
	};
}

